package com.zhanghe.security.filter;

import com.zhanghe.security.authenticationtoken.RefreshTokenAuthenticationToken;
import com.zhanghe.security.excepiton.RefreshtokenExpireException;
import com.zhanghe.security.property.SecurityProperties;
import com.zhanghe.security.service.SimpleUserDetailsService;
import com.zhanghe.security.util.JwtUtil;
import com.zhanghe.security.util.R;
import com.zhanghe.security.util.ResponseUtil;
import com.zhanghe.security.util.ReturnCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RefreshTokenFilter extends AbstractAuthenticationProcessingFilter {
    protected static final Logger logger = LoggerFactory.getLogger(RefreshTokenFilter.class);

    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private SimpleUserDetailsService simpleUserDetailsService;

    public RefreshTokenFilter(String defaultFilterProcessesUrl,AuthenticationManager authenticationManage) {
        super(defaultFilterProcessesUrl);
        setAuthenticationManager(authenticationManage);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
//        String refreshToken = httpServletRequest.getParameter("refreshToken");
        String refreshToken = httpServletRequest.getHeader("refresh-token");
        return getAuthenticationManager().authenticate(new RefreshTokenAuthenticationToken(refreshToken));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        logger.debug("refresh成功");
        RefreshTokenAuthenticationToken refreshTokenAuthenticationToken = (RefreshTokenAuthenticationToken) authResult;
        Map<String,Object> params = new HashMap<String,Object>();
        List<String> roles = new ArrayList<String>();
        for(GrantedAuthority authority:authResult.getAuthorities()){
            roles.add(authority.getAuthority());
        }
        params.put("roles",roles);
        String access_token = JwtUtil.sign(refreshTokenAuthenticationToken.getUserName(),params,securityProperties.getTokensecret(),securityProperties.getTokenExpireMinutes() * 60 * 1000);
        String refresh_token = JwtUtil.sign(refreshTokenAuthenticationToken.getUserName(),new HashMap<String,Object>(0),securityProperties.getTokensecret(),securityProperties.getRefreshTokenExpireTime() * 60 * 1000);
        R r = new R(access_token,refresh_token);
        ResponseUtil.writeResponse(request,response,r.toString(),securityProperties.getOrigins());
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        logger.debug("refresh登录失败:{}",failed.getMessage());
        if(failed instanceof  RefreshtokenExpireException){
            R r = new R(ReturnCode.REFRESH_FAILED,"");
            ResponseUtil.writeResponse(request,response,r.toString(),securityProperties.getOrigins());
        }else{
            R r = new R(ReturnCode.REFRESH_TOKEN_NULL,"");
            ResponseUtil.writeResponse(request,response,r.toString(),securityProperties.getOrigins());
        }
    }
}
